package com.woniuxy.usercoachassemble.controller;


import com.woniuxy.usercoachassemble.annotation.NoRepeatSubmit;
import com.woniuxy.usercoachassemble.commons.*;
import com.woniuxy.usercoachassemble.entity.*;
import com.woniuxy.usercoachassemble.service.*;
import org.example.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.net.URLEncoder;

/**
 * ClassName: RegistController
 * Description: 注册用户控制层
 * date: 2020/7/9 11:18
 *
 * @author Fy浪迹
 */
@RestController
@RequestMapping("register")
public class RegisterController {

    private static int count = 0;

    @NoRepeatSubmit
    @GetMapping("test")
    public Object test(){
        System.out.println(count++);
        return count + "";
    }

    @Autowired
    private AdressService adressService;

    @Autowired
    private UserService userService;

    @Autowired
    private EmailUtils emailUtils;

    @Autowired
    private UserinfoService userinfoService;

    @Autowired
    private CoachInfoService coachInfoService;

    @Autowired
    private YogaGymInfoService yogaGymInfoService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private MemberService memberService;
    @Autowired
    private StringRedisTemplate redisTemplate;


    /**
     * @description:TODO(通过邮箱方式注册)
     * @param email  邮箱
     * @param password 密码
     * @param role 角色 1.用户 2.教练
     * @return:  org.example.Result
     * @author: Fy浪迹、
     * @date: 2020/7/9 16:19
     */
    @PostMapping("registByEamil")
    public Result registByEamil(String email,String password,Integer role) throws Exception {

        System.out.println(role);
        // 校验邮箱格式
        if(email == null || email.isEmpty() || !ValidatorUtils.isEmail(email)){
           return Result.Error(600,"邮箱格式错误");
        }
        // 检验密码
        if(password == null || password.isEmpty()||!ValidatorUtils.isPassword(password)){
            return Result.Error(600,"密码格式错误");
        }
        // 校验角色
        if(role == null || !(role>=1 && role <=3)){
            return Result.Error(600,"角色格式错误");
        }
        // 判断邮箱是否已注册
        User userRex = userService.selectUserByEmail(email);
        if(userRex != null){
            return Result.Error(600,"邮箱已经被注册");
        }
        // 预注册,但未激活
        User user = new User();
        user.setEmail(email);
        user.setPassword(password);
        user.setRoleId(role);
        user.setStatus(1);

        user = userService.registerByEmail(user);
        if(user == null){
            return  Result.Error(600,"服务错误,新增失败");
        }
        // 拼接用户id 邮箱 密码 role 并加密 以逗号分隔
        String ciphertext = user.getUserId() + "," + user.getEmail() + "," + user.getPassword() + "," + user.getRoleId();
        // 验证链接
        String encode = AESHelper.encode(ciphertext);

        String lj = ConstantPool.PROJECT_GATEWAY_WEBROOTPATH +"register/registeredMailVerify?ciphertext="+encode;
        System.out.println(lj);
        String encode1 = URLEncoder.encode(lj, "UTF-8");
        System.out.println(encode1);
        Result result = new Result();
        result.setCode(600);
        result.setData(encode1);
        result.setCode(200);
        result.setMessage("注册成功,请通过邮箱进行激活");

        emailUtils.sendMail(email,"瑜伽App,账号激活","注册成功,点击链接进行激活:"+lj);



        return  result;
    }


    /**
     * @description:TODO(邮箱注册验证)
     * @param ciphertext 激活校验码
     * @return:  com.woniuxy.yogautil.Result
     * @author: Fy浪迹、
     * @date: 2020/7/9 11:49
     */
    @GetMapping("registeredMailVerify")
    public Result registeredMailVerify(String ciphertext) throws Exception {
        //将空格转化为 + 号
        ciphertext = ciphertext.replaceAll(" +","+");
        String decode = AESHelper.decode(ciphertext);
        System.out.println(decode);
        String[] userArray = decode.split(",");

        Integer userId = Integer.parseInt(userArray[0]);
        String email = userArray[1];
        String passwrod = userArray[2];
        Integer role = Integer.parseInt(userArray[3]);

        // 根据userId 查询 用户
        User user  =  userService.selectUserById(userId);

        if(user == null){
            return Result.Error(600,"激活失败");
        }



        if(!(email.equals(user.getEmail()) && passwrod.equals(passwrod) && role.equals(user.getRoleId()))){
             return Result.Error(600,"验证失败,激活失败！");
        }

        if(user.getStatus() > 1){
            return Result.Error(600,"该账号已激活！");
        }


        // 修改账号状态为已激活
        int update = userService.updateUserStatusById(userId,2);

        if(update > 1){
            return Result.Error(600,"未知错误,激活失败");
        }

        user.setPassword(null);


        Result success = Result.Success(user);
        success.setMessage("激活成功");
        boolean b = finishInfo(userId, role);
        if(b){
            return success;
        }

        return Result.Error(500,"服务器繁忙");
    }

    /**
     * @description:TODO(发送找回密码邮件)
     * @param email
     * @return:  org.springframework.web.servlet.ModelAndView
     * @author: Fy浪迹、
     * @date: 2020/7/13 9:43
     */
    @PostMapping("sendRetrievePasswordEmail")
    @NoRepeatSubmit
    public Result sendRetrievePasswordEmail(String email){

        System.out.println(email);
        // 判断邮箱格式
        if(email == null || email.isEmpty() || !ValidatorUtils.isEmail(email)){
           return Result.Error(600,"邮箱格式不正确");
        }
        // 判断邮箱是否存在
        User user = userService.selectUserByEmail(email);
        if(user==null){
            return Result.Error(600,"邮箱不存在");
        }

        // 生成token用户重置密码时验证身份
        String token = UUID.randomUUID().toString();

        // 验证token存入redis 设置失效时间
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        opsForValue.set(ConstantPool.Email_RETRIEVE_PASSWORD_CODE_PREFIX+token,email,60,TimeUnit.MINUTES);

        String appUrl = ConstantPool.EMAIL_RESET_PASSWORD;
        // 发送邮箱
        emailUtils.sendMail(email,"[瑜伽App]忘记密码","您正在申请重置密码，请点击此链接重置密码: \n" + appUrl + "?token=" + token);

        return Result.Success("发送成功!,请查看邮箱进行重置密码");
    }

    /**
     * @description:TODO(通过邮箱方式重置密码)
     * @param password 新密码
     * @param confirmPassword 确认密码
     * @param token 凭证
     * @return:  org.example.Result
     * @author: Fy浪迹、
     * @date: 2020/7/13 10:20
     */
    @PostMapping("retrievePasswordByEmail")
    public Object retrievePasswordByEmail(String password,String confirmPassword,String token){
        // 验证参数是否正确
        if(ValidatorUtils.isNullOrEmpty(password)||ValidatorUtils.isNullOrEmpty(confirmPassword)||ValidatorUtils.isNullOrEmpty(token)){
            return  Result.Error(600,"传入参数不能为空");
        }
        // 验证密码格式
        if(!ValidatorUtils.isPassword(password)){
            return  Result.Error(600,"密码格式错误");
        }

        // 验证两次密码是否一致
        if(!password.equals(confirmPassword)){
            return  Result.Error(600,"两次密码不一致");
        }

        // 验证该token是否存在或失效
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        // 获取存入的email
        String email = opsForValue.get(ConstantPool.Email_RETRIEVE_PASSWORD_CODE_PREFIX + token);


        // 验证token是否失效
        if(email == null || email.isEmpty()) {
            return Result.Error(600, "该重置请求不存在或已失效");
        }

        // 修改密码
        int i = userService.updatePasswordByEmail(email,password);

        if(i<0){
            return Result.Error(500, "服务器未知错误!");
        }
        // 清除存入redis缓存
       // opsForValue.set("ConstantPool.Email_RETRIEVE_PASSWORD_CODE_PREFIX "+ token,"0",0,TimeUnit.MILLISECONDS);

        redisTemplate.delete("ConstantPool.Email_RETRIEVE_PASSWORD_CODE_PREFIX "+ token);
        return "重置密码成功";
    }



    /**
     * @description:TODO(通过电话号码注册)
     * @param tel
     * @param role
     * @return:  org.example.Result
     * @author: Fy浪迹、
     * @date: 2020/7/10 9:49
     */
    @PostMapping("registByTel")
    public Result registByTel(String tel,Integer role,String code){

        // 校验电话号码格式是否正确
        if(tel == null || tel.isEmpty() || !ValidatorUtils.isMobile(tel)){
            return Result.Error(600,"电话格式错误");
        }

        // 校验角色
        if(role == null || !(role>=1 && role <=2)){
            return Result.Error(600,"角色格式错误");
        }

        // 判断电话号码是否已经被注册
        User userRegister = userService.selectUserByTel(tel);
        if(userRegister != null){
            return Result.Error(600,"该电话号已经被注册!");
        }

        // 检验code是否为空
        if(code == null || code.isEmpty()){
            return Result.Error(600,"验证码不能为空!");
        }

        // 检验code格式
        if(!code.matches("[0-9]{6}+")){
            return Result.Error(600,"验证码位数不正确!");
        }

        // 判断验证码是否存在或是否失效
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        System.out.println(ConstantPool.TEL_REGISTER_CODE_PREFIX + "tel");

        String code1 = opsForValue.get(ConstantPool.TEL_REGISTER_CODE_PREFIX + tel);
        System.out.println(code1);
        if(code1 == null || code1.isEmpty()){
            return Result.Error(600,"验证码已失效或还未获取验证,请重新获取验证码！");
        }

        // 判断验证码是否错误
        if(!code.equals(code1)){
            return Result.Error(600,"验证码错误！");
        }

        // 根据电话号注册
        User user1 = userService.registerByTel(tel,role);

        Result success = Result.Success(user1);
        success.setMessage("注册成功");
        return success;
    }


    /**
     * @description:TODO(通过电话号码注册)
     * @param tel
     * @param role
     * @return:  org.example.Result
     * @author: Fy浪迹、
     * @date: 2020/7/10 9:49
     */
    @PostMapping("registByTelAndPassword")
    public Result registByTelAndPassword(String tel,Integer role,String code,String password){

        // 校验电话号码格式是否正确
        if(tel == null || tel.isEmpty() || !ValidatorUtils.isMobile(tel)){
            return Result.Error(600,"电话格式错误");
        }

        // 检验密码
        if(password == null || password.isEmpty()||!ValidatorUtils.isPassword(password)){
            return Result.Error(600,"密码格式错误");
        }

        // 校验角色
        if(role == null || !(role>=1 && role <=3)){
            return Result.Error(600,"角色格式错误");
        }

        // 判断电话号码是否已经被注册
        User userRegister = userService.selectUserByTel(tel);
        if(userRegister != null){
            return Result.Error(600,"该电话号已经被注册!");
        }

        // 检验code是否为空
        if(code == null || code.isEmpty()){
            return Result.Error(600,"验证码不能为空!");
        }

        // 检验code格式
        if(!code.matches("[0-9]{6}+")){
            return Result.Error(600,"验证码位数不正确!");
        }

        // 判断验证码是否存在或是否失效
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        System.out.println(ConstantPool.TEL_REGISTER_CODE_PREFIX + "tel");

        String code1 = opsForValue.get(ConstantPool.TEL_REGISTER_CODE_PREFIX + tel);
        System.out.println(code1);
        if(code1 == null || code1.isEmpty()){
            return Result.Error(600,"验证码已失效或还未获取验证,请重新获取验证码！");
        }

        // 判断验证码是否错误
        if(!code.equals(code1)){
            return Result.Error(600,"验证码错误！");
        }



        // 根据电话号注册
        User user1 = userService.registerByTelAndPassword(tel, role, password);




        Result success = Result.Success();
        success.setMessage("注册成功");

        boolean b = finishInfo(user1.getUserId(), role);

        if(b){
            return success;
        }



        return Result.Error(500,"服务器繁忙");
    }


    public boolean finishInfo(Integer userId,Integer role){
        // 积分
        Member member = new Member();
        member.setUserId(userId);
        member.setScore(3000);
        member.setAggregateScore(3000);
        member.setLevel(1);
        memberService.save(member);

        // 地址
        Adress adress = new Adress();
        adress.setUserId(userId);
        boolean save = adressService.save(adress);

        // 设置账户
        Account account = new Account();
        String acccountName = UUIDUtils.getRandomNickname();
        account.setAcccountName(acccountName);
        account.setStatus(1);
        account.setMoney(50.0);
        accountService.save(account);

        Account acccount_name = accountService.query().eq("acccount_name", acccountName).one();



        Userinfo userinfo = new Userinfo();
        userinfo.setUserId(userId);
        userinfo.setNickname(UUIDUtils.getRandomNickname());
        userinfo.setInfoLevel(2);
        userinfo.setAcccountId(acccount_name.getAcccountId());
        userinfo.setHeadPortrait(ConstantPool.DEFAULT_AVATAR);
        if(role == 1){
            userinfoService.save(userinfo);
            return true;
        }

        CoachInfo coachInfo = new CoachInfo();
        coachInfo.setIndentification(1);
        coachInfo.setUserId(userId);
        coachInfo.setB("1");
        coachInfo.setPersonalTrainer(1);

        if(role == 2){
            userinfoService.save(userinfo);
            coachInfoService.save(coachInfo);
            return  true;
        }


        YogaGymInfo yogaGymInfo = new YogaGymInfo();
        yogaGymInfo.setA1(1);
        yogaGymInfo.setUserId(userId);
        if(role == 3){
            userinfoService.save(userinfo);
            yogaGymInfoService.save(yogaGymInfo);
            return true;
        }
        return false;
    }

    /**
     * @description:TODO(获取手机注册验证码)
     * @param tel
     * @param role
     * @return:  org.example.Result
     * @author: Fy浪迹、
     * @date: 2020/7/10 11:31
     */
    @PostMapping("getRegisterCode")
    public Result getRegisterCode(String tel,Integer role){

        // 校验电话号码格式是否正确
        if(tel == null || tel.isEmpty() || !ValidatorUtils.isMobile(tel)){
            return Result.Error(600,"电话格式错误");
        }


        // 判断电话号码是否已经被注册
        User userRegister = userService.selectUserByTel(tel);
        if(userRegister != null){
            return Result.Error(600,"该电话号已经被注册");
        }

        // 随机生成6位数code
        String code = RandomUtils.get6PlaceNum() + "";
        System.out.println(code);
        // 发送短信 电话号码,发送模板:注册,验证码
        boolean b = SMSUtils.sendSMS(tel, SMSUtils.TEMPLATECODE_REGISTER, code);
//        boolean b = true;
        if(!b){
            return Result.Error(600,"发送失败");
        }


        // 将手机号code 存入redis
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        opsForValue.set(ConstantPool.TEL_REGISTER_CODE_PREFIX+tel,code,5,TimeUnit.MINUTES);
        Result success = Result.Success();
        success.setMessage("验证码已发送");
        return success;
    }


    /**
     * @description:TODO(获取找回密码验证码)
     * @param tel
     * @return:  org.example.Result
     * @author: Fy浪迹、
     * @date: 2020/7/10 16:53
     */
    @PostMapping("getRetrievePasswordCode")
    public Result getRetrievePasswordCode(String tel){
        // 校验电话号码格式是否正确
        if(tel == null || tel.isEmpty() || !ValidatorUtils.isMobile(tel)){
            return Result.Error(600,"手机号格式错误");
        }

        // 判断电话号码是否存在
        User userRegister = userService.selectUserByTel(tel);
        if(userRegister == null){
            return Result.Error(600,"手机号不存在");
        }


        // 随机生成6位数code
        String code = RandomUtils.get6PlaceNum() + "";
        System.out.println(code);
        // 发送短信 电话号码,发送模板:找回密码,验证码
         boolean b = SMSUtils.sendSMS(tel, SMSUtils.TEMPLATECODE_RETRIEVE_PASSWORD, code);
//        boolean b = true;
        if (!b) {
            return Result.Error(600, "发送失败");
        }
        // 将手机号找回密码code 存入redis
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        opsForValue.set(ConstantPool.TEL_RETRIEVE_PASSWORD_CODE_PREFIX+tel,code,3,TimeUnit.MINUTES);
        Result success = Result.Success();
        success.setMessage("验证码已发送");
        return success;

    }

    /**
     * @description:TODO(根据电话验证码重置密码)
     * @param tel
     * @param password
     * @param code
     * @return:  org.example.Result
     * @author: Fy浪迹、
     * @date: 2020/7/10 17:17
     */
    @PostMapping("retrievePasswordByTelCode")
    public Result retrievePasswordByTelCode(String tel,String password,String code){

        // 校验电话号码格式是否正确
        if(tel == null || tel.isEmpty() || !ValidatorUtils.isMobile(tel)){
            return Result.Error(600,"手机号格式错误");
        }
        // 判断电话号码是否存在
        User userRegister = userService.selectUserByTel(tel);
        if(userRegister == null){
            return Result.Error(600,"手机号不存在");
        }
        // 检验code是否为空
        if(code == null || code.isEmpty()){
            return Result.Error(600,"验证码不能为空!");
        }
        // 检验code格式
        if(!code.matches("[0-9]{6}+")){
            return Result.Error(600,"验证码位数不正确!");
        }
        // 检验密码
        if(password == null || !ValidatorUtils.isPassword(password)) {
            return Result.Error(600, "密码格式错误");
        }

        // 判断验证码是否存在或是否失效
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        System.out.println(ConstantPool.TEL_RETRIEVE_PASSWORD_CODE_PREFIX + "tel");

        String code1 = opsForValue.get(ConstantPool.TEL_RETRIEVE_PASSWORD_CODE_PREFIX + tel);
        System.out.println(code1);
        if(code1 == null || code1.isEmpty()){
            return Result.Error(600,"验证码已失效或还未获取验证,请重新获取验证码！");
        }

        // 判断验证码是否正确
        if(!code.equals(code1)){
            return Result.Error(600,"验证码错误！");
        }


        // 修改密码
        User user = userService.updatePasswordByTel(tel,password);

        if(user == null){
            return Result.Error(600,"修改密码失败!");
        }


        Result success = Result.Success();
        success.setMessage("重置密码成功");
        return success;
    }


    /**
     * @description:TODO(根据电话验证码重置密码)
     * @param tel
     * @param password
     * @param code
     * @return:  org.example.Result
     * @author: Fy浪迹、
     * @date: 2020/7/10 17:17
     */
    @PostMapping("retrieveDoublePasswordByTelCode")
    public Result retrieveDoublePasswordByTelCode(String tel,String password,String confirmPassword,String code){

        // 校验电话号码格式是否正确
        if(tel == null || tel.isEmpty() || !ValidatorUtils.isMobile(tel)){
            return Result.Error(600,"手机号格式错误");
        }


        // 判断电话号码是否存在
        User userRegister = userService.selectUserByTel(tel);
        if(userRegister == null){
            return Result.Error(600,"手机号不存在");
        }


        // 检验code是否为空
        if(code == null || code.isEmpty()){
            return Result.Error(600,"验证码不能为空!");
        }
        // 检验code格式
        if(!code.matches("[0-9]{6}+")){
            return Result.Error(600,"验证码位数不正确!");
        }
        // 检验密码
        if(password == null || !ValidatorUtils.isPassword(password)) {
            return Result.Error(600, "密码格式错误");
        }

        if(!password.equals(confirmPassword)){
            return Result.Error(600, "两次密码不一致");
        }

        // 判断验证码是否存在或是否失效
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        System.out.println(ConstantPool.TEL_RETRIEVE_PASSWORD_CODE_PREFIX + "tel");

        String code1 = opsForValue.get(ConstantPool.TEL_RETRIEVE_PASSWORD_CODE_PREFIX + tel);
        System.out.println(code1);
        if(code1 == null || code1.isEmpty()){
            return Result.Error(600,"验证码已失效或还未获取验证,请重新获取验证码！");
        }

        // 判断验证码是否正确
        if(!code.equals(code1)){
            return Result.Error(600,"验证码错误！");
        }


        // 修改密码
        User user = userService.updatePasswordByTel(tel,password);

        if(user == null){
            return Result.Error(600,"修改密码失败!");
        }


        Result success = Result.Success();
        success.setMessage("重置密码成功");
        return success;
    }




}
